package com.asen.business.commons.service.impl;

import com.asen.business.commons.domain.BaseBill;
import com.asen.business.commons.service.BaseBillService;
import com.asen.commons.core.base.enums.ActionTypeEnum;
import com.asen.commons.core.listener.ServiceContext;
import com.asen.commons.core.meta.dao.Condition;
import com.asen.commons.utils.BaseAssert;
import com.asen.commons.utils.IdUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

/**
 * 基础资料Service抽象类
 *
 * @author Gary
 * @version 1.0
 * @date 2018-12-09
 */
public abstract class AbstractBaseBillServiceImpl<T extends BaseBill> extends AbstractBillServiceImpl<T> implements BaseBillService<T> {

    // TODO
    //@Autowired
    //@Qualifier("cacheDataManager")
    //protected CacheManager cacheManager;
    //
    //@Autowired
    //protected CacheDataConfig cacheDataConfig;

    //@Autowired
    //private RedisCache redisCache;

    @Override
    protected void addValidate(T model) throws Exception {
        super.addValidate(model);

        BaseAssert.notEmpty(model.getName(), "名称不能为空");

        if (StringUtils.isNotEmpty(model.getNumber())) {
            checkDupByNumber(null, model.getNumber());
        }
    }

    @Override
    protected void beforeAdd(T model) throws Exception {
        super.beforeAdd(model);

        if (model.getIsEnabled() == null) {
            // 新增默认启用
            model.setIsEnabled(Boolean.TRUE);
        }

        if (StringUtils.isEmpty(model.getNumber())) {
            // 设置默认编码规则
            setAutoNumber(model);
        } else {
            checkDupByNumber(null, model.getNumber());
        }
    }

    @Override
    protected void afterAdd(T model) throws Exception {
        super.afterAdd(model);

        // 缓存
        cache(model);
    }

    @Override
    protected void updateValidate(T model) throws Exception {
        super.updateValidate(model);
        BaseAssert.notEmpty(model.getNumber(), "编码不能为空");
        BaseAssert.notEmpty(model.getName(), "名称不能为空");
        checkDupByNumber(model.getId(), model.getNumber());
    }

    @Override
    protected void afterUpdate(T model) throws Exception {
        super.afterUpdate(model);

        // 缓存
        cache(model);
    }

    @Override
    protected void afterRemove(T model) throws Exception {
        super.afterRemove(model);

        // 缓存
        cacheRemove(model);
    }



    /**
     * 缓存
     *
     * @param model
     * @throws Exception
     */
    protected void cache(T model) throws Exception {
        // TODO
        //if (model.getId() == null) {
        //    return;
        //}
        //CacheItemConfig config = cacheDataConfig.get(getModelClass().getSimpleName());
        //if (config == null) {
        //    config = cacheDataConfig.get(getModelClass().getName());
        //}
        //if (config != null) {
        //    redisCache.removeLike(CacheTypeEnum.BAS_DATA, this.getModelClass().getName());
        //    if (config.isCacheCode()) {
        //        cacheManager.setCode(this.getModelClass(), model.getId(), model.getNumber());
        //    }
        //    if (config.isCacheName()) {
        //        cacheManager.setName(this.getModelClass(), model.getId(), model.getName());
        //    }
        //    if (config.isCacheObject()) {
        //        cacheManager.setObjectVo(model.getId(), model);
        //    }
        //}
    }

    /**
     * 缓存
     *
     * @param model
     * @throws Exception
     */
    protected void cacheRemove(T model) throws Exception {
        if (model.getId() == null) {
            return;
        }
        // TODO
        //CacheItemConfig config = cacheDataConfig.get(getModelClass().getSimpleName());
        //if (config == null) {
        //    config = cacheDataConfig.get(getModelClass().getName());
        //}
        //if (config != null) {
        //    redisCache.removeLike(CacheTypeEnum.BAS_DATA, this.getModelClass().getName());
        //}
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void enable(Long id) throws Exception {
        BaseAssert.check(IdUtils.isNotEmpty(id), "参数id不能为空");
        T model = this.get(id);
        beforeEnable(model);
        ServiceContext serviceContext = createServiceContext(model, ActionTypeEnum.ENABLE);
        beforeListener(serviceContext);

        model.setIsEnabled(true);
        updatePartial(model, "isEnabled");

        afterEnable(model);
        afterListener(serviceContext);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void disable(Long id) throws Exception {
        BaseAssert.check(IdUtils.isNotEmpty(id), "参数id不能为空");
        T model = this.get(id);
        beforeDisable(model);
        ServiceContext serviceContext = createServiceContext(model, ActionTypeEnum.DISABLE);
        beforeListener(serviceContext);

        model.setIsEnabled(false);
        updatePartial(model, "isEnabled");

        afterDisable(model);
        afterListener(serviceContext);
    }

    @Override
    public T getByNumber(String number) throws Exception {
        Condition condition = new Condition();
        condition.equal("number", number);
        return getBy(condition);
    }

    @Override
    public T getByName(String number) throws Exception {
        Condition condition = new Condition();
        condition.equal("name", number);
        return getBy(condition);
    }

    @Override
    public void checkDupByName(Long id, String name) throws Exception {
        if (StringUtils.isEmpty(name)) {
            return;
        }

        Condition condition = new Condition();
        if (id != null && id > 0L) {
            condition.notEqual("id", id);
        }
        condition.equal("name", name);
        int count = count(condition);
        BaseAssert.check(count == 0, "名称重复");
    }

    protected void beforeEnable(T model) throws Exception {

    }

    protected void afterEnable(T model) throws Exception {
        cache(model);
    }

    protected void beforeDisable(T model) throws Exception {

    }

    protected void afterDisable(T model) throws Exception {
        cache(model);
    }
}
